package com.such.kit.database;

import java.util.HashSet;
import java.util.Set;
import com.such.kit.string.StringCommons;
import com.such.kit.validate.ValidateCommons;

/**
 * @作者 SUCH
 * @日期 2017-9-14 下午6:09:36
 * @描述 DDL 语句格式化工具类
 */
public class DDLFormatter {

	/** initialLine：需要换行的特殊字符 */
	private static Set<String> initialLineSet = new HashSet<String>();
	static {
		initialLineSet.add(",");
	}

	public static String format(String ddl) {
		StringBuffer ddlsBuf = new StringBuffer();
		if (ValidateCommons.isNotEmpty(ddl)) {
			ddl = ddl.trim();
			int ddlLen = ddl.length();

			boolean hasWhiteSpace = false;
			boolean hasQuote = false;
			int checkDepth = getCheckDepth(ddl);
			int bracketDepth = 1;
			String surplusDDL = null;
			for (int i = 0; i < ddlLen; i++) {
				char ch = ddl.charAt(i);
				// 跳过多余的空格
				if (' ' == ch) {
					if (hasWhiteSpace) {
						continue;
					} else {
						hasWhiteSpace = true;
					}
				} else {
					hasWhiteSpace = false;
				}
				// 检查是否有引号，如果有引号对特殊字符不做处理
				if ('\"' == ch || '`' == ch || '\'' == ch) {
					if (hasQuote) {
						hasQuote = false;
					} else {
						hasQuote = true;
					}
				}
				if (!hasQuote) {
					// 遇 DDL 结束符 ; 则进行换行
					if (';' == ch) {
						ddlsBuf.append(ch).append(StringCommons.NEW_LINE);
						// 重新获取下一段 DDL 的 checkDepth
						surplusDDL = ddl.substring(i + 1);
						if (ValidateCommons.isNotEmpty(surplusDDL)) {
							checkDepth = getCheckDepth(surplusDDL);
						}
						continue;
					}
					// 处理需要换行的特殊字符
					// 只对第 checkDepth 层括号后的(+1) , 进行换行
					if (initialLineSet.contains(String.valueOf(ch)) && bracketDepth == (checkDepth + 1)) {
						ddlsBuf.append(ch);
						if (i + 1 < ddlLen) {
							// 检查后续字符是否是空格，是则删除
							ch = ddl.charAt(i + 1);
							hasWhiteSpace = (' ' == ch);
							while (hasWhiteSpace) {
								i++;
								ch = ddl.charAt(i + 1);
								hasWhiteSpace = (' ' == ch);
							}
						}
						ddlsBuf.append(StringCommons.NEW_LINE).append(StringCommons.RETRACT);
						continue;
					}
					// 处理括号
					// 只对第 checkDepth 层括号进行换行
					if ('(' == ch) {
						if (bracketDepth == checkDepth) {
							ddlsBuf.append(ch).append(StringCommons.NEW_LINE).append(StringCommons.RETRACT);
						} else {
							ddlsBuf.append(ch);
						}
						bracketDepth++;
						continue;
					}
					if (')' == ch) {
						bracketDepth--;
						if (bracketDepth == checkDepth) {
							ddlsBuf.append(StringCommons.NEW_LINE).append(ch);
						} else {
							ddlsBuf.append(ch);
						}
						continue;
					}
				}
				ddlsBuf.append(ch);
			}
		}
		return ddlsBuf.toString();
	}

	private static int getCheckDepth(String ddl) {
		int checkDepth = 1;
		// 匹配 alter table xxx add | modify xxx number(10, 2) xxx
		if (ValidateCommons.matchRule(StringCommons.toLowerCase(ddl), "(alter table)[\\s\\S]{0,}(add|modify)[\\s\\S]{0,}(\\([0-9]{1,}[,]{0,1}[\\s]{0,}[0-9]{1,}\\))[\\s\\S]{0,}")) {
			// alter table 中数据类型的括号不换号
			checkDepth = -1;
		}
		return checkDepth;
	}

}
